import { Injectable } from '@nestjs/common';
import { RolesPageQuery } from './dto/roles.page.query';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { SysRole } from './entities/role.entity';
import { PageResult } from '../../common/result/PageResult';
import { Result } from '../../common/result/Result';
import { RolesForm } from './dto/roles.form';
import { ResultCode } from '../../common/result/ResultCode';
import { JwtUtils } from '../01_auth/jwt.utils';
import { SysRoleMenu } from './entities/role.menu.entity';
import { JwtPayload } from '../01_auth/jwt.payload';

@Injectable()
export class RoleService {
  constructor(
    @InjectRepository(SysRole)
    private roleRepository: Repository<SysRole>, // mysql数据库连接工具

    @InjectRepository(SysRoleMenu)
    private roleMenuRepository: Repository<SysRoleMenu>,
    private jwt: JwtUtils, // 验签管理器（token）
  ) {}
  async getPage(query: RolesPageQuery): Promise<PageResult<SysRole>> {
    const queryBuilder = this.roleRepository
      .createQueryBuilder('su')
      .skip((query.pageNum - 1) * query.pageSize)
      .take(query.pageSize);
    if (query.keywords) {
      queryBuilder.andWhere(
        '(su.name LIKE :keywords OR su.code LIKE :keywords)',
        { keywords: `%${query.keywords}%` },
      );
    }
    const result = await queryBuilder.getManyAndCount();
    return PageResult.success(result[0], result[1]);
  }

  async getOptions(): Promise<Result<any>> {
    const many = await this.roleRepository
      .createQueryBuilder('u')
      .select('u.id as value,u.name as label')
      .orderBy('sort')
      .getRawMany();
    return Result.success(many);
  }

  async saveRole(form: RolesForm, payload: JwtPayload): Promise<Result<any>> {
    // 1. 检验该角色是否存在
    const flag = await this.roleRepository.exists({
      where: { code: form.code },
    });
    if (flag) {
      return Result.failed(ResultCode.ROLE_HAS_EXISTS);
    }
    // 2. 插入角色信息
    const role = new SysRole({
      createUser: payload.nickname,
      createBy: payload.userId,
      updateUser: payload.nickname,
      updateBy: payload.userId,
    });
    // 3. 插入
    role.code = form.code;
    role.status = form.status;
    role.sort = form.sort;
    role.dataScope = form.dataScope;
    role.name = form.name;
    await this.roleRepository.save(role);
    return Result.success();
  }

  async getForm(roleId: number) {
    const role = await this.roleRepository.findOne({ where: { id: roleId } });
    return Result.success(
      new RolesForm({
        id: role.id,
        name: role.name,
        code: role.code,
        dataScope: role.dataScope,
        sort: role.sort,
        status: role.status,
      }),
    );
  }

  async updateRole(form: RolesForm, currentUser: JwtPayload, id: number) {
    // 1. 检验该角色是否存在
    const flag = await this.roleRepository.findOne({
      where: { code: form.code },
    });
    if (flag.id != id) {
      return Result.failed(ResultCode.ROLE_HAS_EXISTS);
    }
    // 2. 插入角色信息
    const role = new SysRole({
      createUser: currentUser.username,
      createBy: currentUser.userId,
      updateUser: currentUser.username,
      updateBy: currentUser.userId,
    });
    // 3. 插入
    role.id = id;
    role.code = form.code;
    role.status = form.status;
    role.sort = form.sort;
    role.dataScope = form.dataScope;
    role.name = form.name;
    await this.roleRepository.update({ id: form.id }, role);
    return Result.success();
  }

  async deleteRoles(ids: string): Promise<Result<string>> {
    // todo 删除角色时应做大量的相关数据CRU工作
    for (const id of ids.split(',')) {
      await this.roleRepository.softDelete({ id: Number(id) });
    }
    return Result.success();
  }

  async getMenuIds(roleId: string) {
    const sql = `SELECT
            rm.menu_id
        FROM
            sys_role_menu rm
            INNER JOIN sys_menu m ON rm.menu_id = m.id
        WHERE
            rm.role_id = @0`;
    const menuIds = await this.roleRepository.query(sql, [roleId]);
    const result: string[] = [];
    menuIds.forEach((menuId) => {
      result.push(menuId.menu_id);
    });
    return Result.success(result);
  }

  async assignMenusToRole(roleId: number, menuIds: number[]) {
    const flag = await this.roleRepository.exists({ where: { id: roleId } });
    if (!flag) {
      return Result.failed(ResultCode.ROLE_CAN_NOT_FOUND);
    }
    // 删除角色菜单
    await this.roleMenuRepository.delete({ roleId: roleId });
    // 新增角色菜单
    for (const menuId of menuIds) {
      const roleMenu = new SysRoleMenu();
      roleMenu.roleId = roleId;
      roleMenu.menuId = menuId;
      await this.roleMenuRepository.save(roleMenu);
    }
    // todo 刷新角色的权限缓存
    return Result.success();
  }

  async updateRoleStatus(roleId: number, status: number) {
    // 1.查询角色是否存在
    const flag = await this.roleRepository.exists({ where: { id: roleId } });
    if (flag) {
      return Result.failed(ResultCode.ROLE_CAN_NOT_FOUND);
    }
    // 2. 修改状态信息
    await this.roleRepository.update({ id: roleId }, { status: status });
    return Result.success();
  }
}
